home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
ARGONET
/
PD
/
FILER
/
GREP.ZIP
/
release
/
c
/
wild
< prev
Wrap
Text File
|
1998-09-23
|
15KB
|
538 lines
/*->c.wild */
/* wildcard code added by David Pilling for the Archimedes */
/* bits taken from C Kermit */
/* Section modified by Justin Fletcher to work with kernel.h and swis.h
rather than arthur.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "kernel.h"
#include "swis.h"
#define MAXWLD 512 /* Maximum wildcard filenames */
#define MAXNAMLEN 255
static int fcount; /* Number of files in wild group */
static char nambuf[MAXNAMLEN+2]; /* Buffer for a filename */
static char *mtchs[MAXWLD], /* Matches found for filename */
**mtchptr; /* Pointer to current match */
/*
* osgbpb with r0==9 is used to read directory names;
* the data returned is copied into a struct dirent.
*/
struct dirent {
unsigned int d_reclen; /* length of this record */
unsigned int d_namlen; /* length of string in d_name */
char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
};
/*
* This macro calculates the amount of storage required for
* the directory entry.
*/
#undef DIRSIZ
#define DIRSIZ(dp) \
((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &3))
/*
* Definitions for library routines operating on directories.
*/
typedef struct _dirdesc
{
long dd_pos; /* current position in directory. */
struct dirent *dd_dirent;
char dd_name[MAXNAMLEN+1]; /* osgbpb needs a name */
char dd_buf[MAXNAMLEN+1]; /* osgbpb needs a buffer */
} DIR;
extern DIR *opendir( char * );
extern void closedir( DIR *);
struct FileData {int loadaddr, execaddr, length, attrib;};
struct BTim {int low, high;};
int
GetFileInformation(
struct FileData *info,
struct BTim *tstamp,
char * name,
int len )
{
static _kernel_osfile_block o_b;
static _kernel_swi_regs rs;
_kernel_oserror *ret;
int objtype;
#define osfind(regs) _kernel_swi(OS_Find,regs,regs)
#define osfile(regs) _kernel_swi(OS_Find,regs,regs)
/* printf("Info on %s\n",name); */
/* Open file for reading */
rs.r[0] = 0x40;
rs.r[1] = (int)name;
if( (ret=osfind( &rs )) != NULL )
{
fprintf(stderr,"%s (%d)\n",ret->errmess,ret->errnum);
return -1;
}
if( rs.r[0] == 0 )
/* File does not exist */
return -1;
/* close the file just opened */
rs.r[1] = rs.r[0];
rs.r[0] = 0;
if( (ret=osfind( &rs )) != NULL )
{
fprintf(stderr,"%s (%d)\n",ret->errmess,ret->errnum);
return -1;
}
/* o_b.action = 5; */
/* o_b.name = name; */
if( (objtype=_kernel_osfile( 5,name,&o_b )) <0 )
{
ret=_kernel_last_oserror();
fprintf(stderr,"%s (%d)\n",ret->errmess,ret->errnum);
return -1;
}
/* printf("Objtype=%i\n",objtype); */
info->loadaddr = o_b.load;
info->execaddr = o_b.exec;
info->length = o_b.start;
info->attrib = o_b.end;
len=0; /* filename len */
tstamp->low=0;
/* Return file type */
return objtype;
}
DIR *
opendir( filename )
char *filename;
{
DIR * dirp;
if( (dirp = (DIR*)malloc(sizeof(DIR))) == NULL )
return NULL;
if( (dirp->dd_dirent =
(struct dirent*)malloc(sizeof(struct dirent))) == NULL )
return NULL;
dirp->dd_pos = 0;
strcpy( dirp->dd_name, filename );
return dirp;
}
struct dirent *
readdir( dirp )
DIR *dirp;
{
static _kernel_osgbpb_block par;
struct dirent *dp;
char *name;
/* par.action = 9; */
/* par.file_handle = (int)dirp->dd_name; */
par.dataptr = dirp->dd_buf;
par.nbytes = 1;
par.fileptr = (int)dirp->dd_pos;
par.buf_len = sizeof( dirp->dd_buf );
par.wild_fld = "*";
/* printf("Doing GBPB on %s\n",dirp->dd_name); */
if( _kernel_osgbpb( 9, (int)dirp->dd_name, &par ) ==-2 )
return NULL;
if( (par.nbytes != 1) || (par.fileptr == -1) )
return NULL;
name = dirp->dd_buf;
/* printf("Read %s\n",name); */
dp = dirp->dd_dirent;
dp->d_namlen = strlen( name );
dp->d_reclen = sizeof(struct dirent) - (MAXNAMLEN+1) +
dp->d_namlen + 1;
strcpy( dp->d_name, name );
dirp->dd_pos++;
return dp;
}
long
telldir( dirp )
DIR *dirp;
{
return dirp->dd_pos;
}
void
seekdir( dirp, loc )
DIR *dirp;
long loc;
{
dirp->dd_pos = loc;
return;
}
void
closedir( dirp )
DIR *dirp;
{
free( dirp->dd_dirent );
free( dirp );
return;
}
/* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */
/*
* The path structure is used to represent the name to match.
* Each slash-separated segment of the name is kept in one
* such structure, and they are linked together, to make
* traversing the name easier.
*/
struct path {
char npart[MAXNAMLEN]; /* name part of path segment */
struct path *fwd; /* forward ptr */
};
#define SSPACE 2000 /* size of string-generating buffer */
static char sspace[SSPACE]; /* buffer to generate names in */
static char *freeptr,**resptr; /* copies of caller's arguments */
static int remlen; /* remaining length in caller's array*/
static int numfnd; /* number of matches found */
void traverse(struct path *,char *,char *);
int match(char *,char *);
void addresult(char *);
int iswild(char *);
/*
* splitpath:
* takes a string and splits the slash-separated portions into
* a list of path structures. Returns the head of the list. The
* structures are allocated by malloc, so they must be freed.
* Splitpath is used internally by the filename generator.
*
* Input: A string.
* Returns: A linked list of the slash-separated segments of the input.
*/
struct path * splitpath(p) char *p;
{
struct path *head,*cur,*prv;
int i;
head = prv = NULL;
if (*p == ':') p+=2;
if (*p== '.') p++;
while (*p != '\0')
{
cur = (struct path *) malloc(sizeof (struct path));
if (cur == NULL) {fprintf(stderr,"malloc fails in splitpath()\n");exit(1);}
cur -> fwd = NULL;
if (head == NULL) head = cur;
else prv -> fwd = cur; /* link into chain */
prv = cur;
for (i=0; i < MAXNAMLEN && *p != '.' && *p != '\0'; i++)
cur -> npart[i] = *p++;
cur -> npart[i] = '\0'; /* end this segment */
if (i >= MAXNAMLEN) while (*p != '.' && *p != '\0') p++;
if (*p == '.') p++;
}
return(head);
}
/*
* fgen:
* This is the actual name generator. It is passed a string,
* possibly containing wildcards, and an array of character pointers.
* It finds all the matching filenames and stores them into the array.
* The returned strings are allocated from a static buffer local to
* this module (so the caller doesn't have to worry about deallocating
* them); this means that successive calls to fgen will wipe out
* the results of previous calls. This isn't a problem here
* because we process one wildcard string at a time.
*
* Input: a wildcard string, an array to write names to, the
* length of the array.
* Returns: the number of matches. The array is filled with filenames
* that matched the pattern. If there wasn't enough room in the
* array, -1 is returned.
* By: Jeff Damens, CUCCA, 1984.
*/
int fgen(pat,resarry,len)
char *pat,*resarry[];
int len;
{
struct path *head;
char scratch[100],*sptr;
head = splitpath(pat);
if (*pat != ':')
{
scratch[0] = '\0';
sptr = scratch;
}
else
{
strcpy(scratch,pat);
scratch[3]=0;
sptr = scratch+3;
}
/* init buffer correctly */
numfnd = 0; /* none found yet */
freeptr = sspace; /* this is where matches are copied */
resptr = resarry; /* static copies of these so*/
remlen = len; /* recursive calls can alter them */
traverse(head,scratch,sptr); /* go walk the directory tree */
for (; head != NULL; head = head -> fwd)
free(head); /* return the path segments */
return(numfnd); /* and return the number of matches */
}
/* traverse:
* Walks the directory tree looking for matches to its arguments.
* The algorithm is, briefly:
* If the current pattern segment contains no wildcards, that
* segment is added to what we already have. If the name so far
* exists, we call ourselves recursively with the next segment
* in the pattern string; otherwise, we just return.
*
* If the current pattern segment contains wildcards, we open the name
* we've accumulated so far (assuming it is really a directory), then read
* each filename in it, and, if it matches the wildcard pattern segment, add
* that filename to what we have so far and call ourselves recursively on the
* next segment.
*
* Finally, when no more pattern segments remain, we add what's accumulated
* so far to the result array and increment the number of matches.
*
* Input: a pattern path list (as generated by splitpath), a string
* pointer that points to what we've traversed so far (this
* can be initialized to "/" to start the search at the root
* directory, or to "./" to start the search at the current
* directory), and a string pointer to the end of the string
* in the previous argument.
* Returns: nothing.
*/
void
traverse(pl,sofar,endcur)
struct path *pl;
char *sofar,*endcur;
{
DIR *fd;
struct dirent dir_entry;
struct dirent *dirbuf = &dir_entry;
struct FileData fileinfo;
struct BTim timeinfo;
int rc;
int stamped;
if (pl == NULL)
{
*--endcur = '\0'; /* end string, overwrite trailing / */
addresult(sofar);
return;
}
if (!iswild(pl -> npart))
{
strcpy(endcur,pl -> npart);
endcur += strlen(pl -> npart);
*endcur = '\0'; /* end current string */
/* if (stat(sofar,&statbuf) == 0) */ /* if current piece exists */
rc = GetFileInformation(&fileinfo, &timeinfo, sofar, strlen(sofar));
if( rc >= 0 ) /* if current piece exists */
{
*endcur++ = '.'; /* add slash to end */
*endcur = '\0'; /* and end the string */
traverse(pl -> fwd,sofar,endcur);
}
return;
}
/* segment contains wildcards, have to search directory */
*endcur = '\0'; /* end current string */
if( *(endcur-1) == '.' )
{
/* Stamp on trailing . */
*--endcur = '\0';
stamped = 1;
}
else
stamped = 0;
/* if (stat(sofar,&statbuf) == -1) return;*/ /* doesn't exist, forget it */
/* if ((statbuf.st_mode & S_IFDIR) == 0) return;*/ /* not a directory, skip */
if( sofar[0] != '\0' )
{
/* cwd is represented as a NULL string!! */
rc = GetFileInformation(&fileinfo, &timeinfo, sofar, strlen(sofar));
if( rc == -1 ) return; /* doesn't exist, forget it */
if( rc != 2 ) return; /* not a directory, skip */
}
if ((fd = opendir(sofar)) == NULL) return; /* can't open, forget it */
if( stamped != 0 )
{
*endcur++ = '.';
*endcur = '\0';
}
while ( (dirbuf = readdir(fd)) != NULL )
{
strncpy(nambuf,dirbuf->d_name,MAXNAMLEN); /* Get a null terminated copy!!! */
nambuf[MAXNAMLEN] = '\0';
/* if (dirbuf->d_ino != 0 && match(pl -> npart,nambuf)) {*/
if ( match(pl -> npart,nambuf)) {
char *eos;
strcpy(endcur,nambuf);
eos = endcur + strlen(nambuf);
*eos = '.'; /* end this segment */
traverse(pl -> fwd,sofar,eos+1);
}
}
closedir(fd);
}
/*
* addresult:
* Adds a result string to the result array. Increments the number
* of matches found, copies the found string into our string
* buffer, and puts a pointer to the buffer into the caller's result
* array. Our free buffer pointer is updated. If there is no
* more room in the caller's array, the number of matches is set to -1.
* Input: a result string.
* Returns: nothing.
*/
void addresult(str)
char *str;
{
int l;
if (strncmp(str,"./",2) == 0) str += 2;
if (--remlen < 0) {
numfnd = -1;
return;
}
l = strlen(str) + 1; /* size this will take up */
if ((freeptr + l) > &sspace[SSPACE-1]) {
numfnd = -1; /* do not record if not enough space */
return;
}
strcpy(freeptr,str);
*resptr++ = freeptr;
freeptr += l;
numfnd++;
}
int iswild(str)
char *str;
{
char c;
while ((c = *str++) != '\0')
if (c == '*' || c == '?') return(1);
return(0);
}
/*
* match:
* pattern matcher. Takes a string and a pattern possibly containing
* the wildcard characters '*' and '?'. Returns true if the pattern
* matches the string, false otherwise.
* by: Jeff Damens, CUCCA
*
* Input: a string and a wildcard pattern.
* Returns: 1 if match, 0 if no match.
*/
int match(pattern,string) char *pattern,*string; {
char *psave,*ssave; /* back up pointers for failure */
psave = ssave = NULL;
while (1) {
for (; toupper(*pattern)==toupper(*string); pattern++,string++)
/* skip first */
if (*string == '\0') return(1); /* end of strings, succeed */
if (*string != '\0' && *pattern == '?') {
pattern++; /* '?', let it match */
string++;
} else if (*pattern == '*') { /* '*' ... */
psave = ++pattern; /* remember where we saw it */
ssave = string; /* let it match 0 chars */
} else if (ssave != NULL && *ssave != '\0') { /* if not at end */
/* ...have seen a star */
string = ++ssave; /* skip 1 char from string */
pattern = psave; /* and back up pattern */
} else return(0); /* otherwise just fail */
}
}
/* Z X P A N D -- Expand a wildcard string into an array of strings */
/*
Returns the number of files that match fn1, with data structures set up
so that first file (if any) will be returned by the next znext() call.
*/
int zxpand(fn) char *fn;
{
fcount = fgen(fn,mtchs,MAXWLD); /* Look up the file. */
if (fcount > 0)
{
mtchptr = mtchs; /* Save pointer for next. */
}
return(fcount);
}
/* Z N E X T -- Get name of next file from list created by zxpand(). */
/*
Returns >0 if there's another file, with its name copied into the arg string,
or 0 if no more files in list.
*/
int znext(fn) char *fn; {
if (fcount-- > 0) strcpy(fn,*mtchptr++);
else *fn = '\0';
return(fcount+1);
}